*
* xmodem protocol version 6.0
*
* commodore 64
*
* this version uses filename
* supplied by calling program
* with construct:
*
*     a$="filename"+chr$(13)
*     sys 49152,a
*
*     wHERE a =  0   iGNORE CARRIER DETECT
*           a = 16   cHECK FOR CARRIER DETECT
*
* note: sETTING a$ *must* BE JUST BEFORE sys49152
*       WITH NO INTERVENING STRING OPERATIONS!
*
* copyright (c) 1986 by
* microtechnic solutions, inc.
* all rights reserved
*
* this version released to public domain
*
 tr on ;TRUNCATION ON (merlin)
 org $c000
*
chkin = $ffc6
chkout = $ffc9
chrout = $ffd2
close = $ffc3
clrchn = $ffcc
getin = $ffe4
open = $ffc0
readss = $ffb7
stop = $ffe1
setlfs = $ffba
setnam = $ffbd
soh = 1
ack = 6
nak = 21
eot = 4
can = 24
varpnt = $47
jiffy = $a1
move = $c3
ridbe = $029b
ridbs = $029c
enable = $02a1
xmoblk = $c700
block = $c800
bln = $c800
blo = $c801
blck1 = $c802
bldata = $c803
blch = $c883
dportb = $dd01
 jmp xmodem
drvdev dfb 8
rcvchr dfb 0
rstat dfb 0
carrier dfb 0
tempx dfb 0
fxmo dfb 0
xmosz dfb 128
lstblk dfb 0
padchr dfb 0
err dfb 0
blknum dfb 0
chrcnt dfb 0
cksum dfb 0
cisfmt dfb 4,0,67,67,51
ebufx dfb 0
tron dfb 128
tbcount da $0000
dskdir dfb 32
tmp2x dfb 0
fbuf ds 80
buf ds 80
ply da $1021
crcdata dfb 0
xmode dfb 0
ctrys dfb 3
xblsz dfb 132
crc da 0
xmodem and #16 ;CARRIER REQUEST 16 OR 0
 sta carrier ;SAVE CARRIER REQUEST
 ldy #1 ;GET THE POINTER TO
 lda (varpnt),y ;THE LAST STRING VARIABLE
 sta move ;REFERENCED BY THE
 iny  ;CALLING bASIC PROGRAM
 lda (varpnt),y
 sta move+1
 clc
 lda move
 adc #1
 sta move
 lda move+1
 adc #0
 sta move+1
 ldy #0
 ldx #0
]jloop lda (move),y ;MOVE THE FILENAME INTO
 cmp #13 ;FILENAME BUFFER
 beq xmd04
 sta fbuf,x
 inx
 iny
 bne ]jloop
xmd04 sty tempx
 ldx tempx
 dex
 lda #0 ;DEFAULT IS TRANSLATION OFF
 sta tron
 lda fbuf,x
 sta tmp2x
 cmp #'T' ;CHECK IF LAST ENTRY IN
 bne xmd05b ;FILENAME IS TRANSLATE
 dex  ;SPECIFIER TO ADJUST FOR
 dex  ;FINDING UP/DOWN
 lda fbuf,x ;SPECIFIER
xmd05b sta dskdir
 cmp #'R' ;IS DIRECTION SPECIFER A
 beq xmd05c ;A VALID ENTRY?
 cmp #'W'
 bne xmd05a
xmd05c dex
 lda #',' ;CHECK FOR INTERVENING COMMA
 cmp fbuf,x
 beq xmd01a
xmd05a lda #6 ;USER MADE AN ERROR IN
 jsr outmsg ;FILENAME SPECIFICATION
 jsr waittwo ;TELL HIM AND THEN EXIT
 jsr xmd19
xmd01a dex
 pha
 lda fbuf,x ;NOW LET US MAKE SURE HE
 cmp #'U' ;SPECIFIED A VALID
 beq xmd01z ;FILE TYPE
 cmp #'P' ;WE WILL ACCEPT U P OR S
 beq xmd01z
 cmp #'S'
 beq xmd01y
 pla
 jmp xmd05a
xmd01y lda #'T' ;GOT BY SYNTAX CHECK
 cmp tmp2x ;NOW CHECK FOR TRANSLATE
 bne xmd01z ;ONLY IF A SEQUENTIAL
 lda #128 ;FILE
 sta tron
xmd01z pla
 dex
 cmp fbuf,x
 bne xmd05a
 lda tempx ;WHEW! NOW WE FINALLY GET
 ldx #<fbuf ;TO OPEN THE DISK FILE
 ldy #>fbuf
 jsr setnam
 lda #8
 jsr opendk
 jsr errchn ;ERROR ON OPEN?
 beq xmd01d ;YES - EXIT
 jsr xmd18
xmd01d lda #2
 jsr outmsg
 lda #3
 sta ctrys
 lda dskdir
 cmp #'R' ;JUMP TO UPLOAD OR DOWNLOAD
 bne xmd06 ;DEPENDING ON DIRECTION
 jmp xmd30 ;SPECIFIED
*
* receive file
*
xmd06 lda #0 ;INITIALIZE EVERYBODY
 sta fxmo
 sta xmode
 sta lstblk
 sta tbcount
 sta tbcount+1
 sta blknum
 jsr setzero
 jsr xmd60 ;GET THINGS ROLLING
 lda #128 ;NORMAL DATA BLOCK SIZE
 sta xmosz
 lda #132
 sta xblsz
 bit xmode ;CHECKSUM OR CRC?
 bmi xmd10 ;CRC
xmd06a lda dportb ;DO WE STILL HAVE CARRIER?
 and carrier
 beq xmd06a1
 jsr xmd28 ;GET VERIFICATION TO ABORT
 beq xmd06a
xmd06a1 jsr setzero
xmd07 jsr gtxmdm ;GO GET A MODEM CHARACTER
 lda dportb ;STILL CHECKING TO SEE IF
 and carrier ;CARRIER PRESENT
 beq xmd07a1
 jsr xmd28
 beq xmd07
xmd07a1 lda chrcnt
 bne xmd10
 lda rcvchr ;LOOK FOR END OF TRANSFER AS
 cmp #eot ;FIRST BYTE OF BLOCK
 bne xmd07a
 jmp xmd42
xmd07a cmp #can ;CHECK FOR USER CANCEL
 bne xmd07b
 jsr xmd19
xmd07b cmp #soh
 bne xmd07
xmd10 jsr chkadd ;ADD THE DATA BYTE TO CHECKSUM
 cmp xblsz ;IS THIS END OF THIS BLOCK?
 bne xmd07 ;NO - GET NEXT CHARACTER
 lda blo ;YES - CHECK BLOCK NUMBER
 clc  ;WITH COMPLEMENT
 adc blck1
 clc
 cmp #255
 beq xmd11 ;BLOCK NUMBER IS GOOD
xmd12 jsr xmd15 ;BLOCK ERROR - SEND A nak
 jmp xmd06a
xmd11 bit xmode ;CHECKSUM OR CRC?
 bpl xmd11a ;CHECKSUM
 lda crc
 ora crc+1
 beq xmd11b
 bne xmd12
xmd11a lda cksum ;NOW SEE IF OUR CALCULATED
 sec  ;CHECKSUM MATCHES THE ONE
 sbc blch ;WE RECEIVED FROM THE SENDER
 clc
 cmp blch
 bne xmd12 ;CHECKSUM ERROR - GO nak
xmd11b inc blknum ;NOW CHECK TO SEE IF THIS IS
 lda block+1 ;THE BLOCK NUMBER WE EXPECTED
 cmp blknum
 beq xmd13
 dec blknum ;OVERLAY PREVIOUS 2ND BUFFER
 jmp xmd14c ;IF SENDER REPEATED HIMSELF
xmd13 lda fxmo ;STUFF INTO 2ND BUFFER IF THIS
 beq xmd14c ;IS THE FIRST BLOCK
xmd14 ldy #0
 ldx #4
xmd14d lda xmoblk,x ;LOOK FOR COMPUSERVE
 cmp cisfmt,x ;MACHINE-SPECIFIC HEADER
 bne xmd14b ;AND STRIP IT OUT
 dex
 bpl xmd14d
 ldy #6
xmd14b sty tempx ;WRITE THE 2ND BUFFER TO DISK
 ldx #8
 jsr chkout
xmd14a ldx tempx
 lda xmoblk,x
 bit tron ;TRANSLATE THE CHARACTERS IF
 bpl xmd14e ;THE TRANSLATE FLAG IS ON
 jsr cnvrt
xmd14e jsr chrout
 jsr readss ;WATCH DEM DISK ERRORS!
 bne xmderr
 inc tempx
 lda xmosz ;IS THIS THE END OF THE
 cmp tempx ;DATA BLOCK PORTION?
 bne xmd14a ;NO - KEEP WRITING TO DISK
 bit lstblk ;YES - IS THIS THE LAST
 bpl xmd14c ;BLOCK OF THE FILE?
 jmp xmd24 ;YES - TIME TO FINISH UP
xmd14c jsr xmdblk ;DISPLAY CURRENT BLOCK INFO
 ldx #0
xmd41 lda bldata,x ;MOVE 1ST BUFFER TO 2ND
 sta xmoblk,x ;WE USE DOUBLE-BUFFERING FOR
 inx  ;ON-THE-FLY PAD STRIPPING
 bpl xmd41 ;MOVE 128 BYTES
 stx fxmo
 lda #ack ;ack THE SENDER - THIS BLOCK
 jsr ptxmdm ;WAS GOOD
 jsr clrchn
 jmp xmd06a
xmderr jsr errchn ;OOPS - GOT A DISK ERROR!
 lda #1 ;NOTIFY THE USER AND THEN
 jsr outmsg ;ABORT THE FILE TRANSFER
 lda #7 ;AT XMD18
 jsr outmsg
 lda #13
 jsr scnout
 jsr xmd18
xmd42 lda #128 ;SET LAST BLOCK INDICATOR
 sta lstblk
 ldx #127 ;DETERMINE WHETHER OR NOT
 lda xmoblk,x ;SENDER USED CTRL-Z OR NULL
 sta padchr ;AS A PAD CHARACTER
 cmp #26
 beq xmd42a ;HE USED CTRL-Z
 cmp #0
 beq xmd42a ;HE USED NULL
 jmp xmd42c
xmd42a lda xmoblk,x ;NOW BACK UP INTO THE LAST
 cmp padchr ;BLOCK UNTIL WE FIND THE
 bne xmd42c ;FINAL REAL DATA BYTE
 dex
 bpl xmd42a
 jmp xmd24
xmd42c inx  ;SET BLOCK SIZE TO MATCH
 stx xmosz ;END OF LAST BLOCK
 jmp xmd14
cnvrt and #127 ;CONVERT ASCII-PETASCII
 cmp #65
 bcc xmd14l
 cmp #91
 bcs xmd14k
 ora #32
 jmp xmd14l
xmd14k cmp #97
 bcc xmd14l
 cmp #123
 bcs xmd14l
 and #223
xmd14l rts
*
* get xmodem char
*
gtxmdm jsr setjif ;SET CHARACTER TIMEOUT
gtx01 jsr stop ;CHECK TO SEE IF USER IS
 beq gtxex ;PRESSING STOP KEY TO ABORT
 jsr gim ;GET CHARACTER FROM MODEM
 bne gtx02 ;WAS THERE A CHARACTER?
 rts  ;YES - RETURN
gtx02 jsr tstjif ;NO - DID WE TIME OUT YET?
 bcc gtx01 ;NO - GO TRY AGAIN
 jsr xmd16 ;YES - GO TO ERROR ROUTINE
 pla
 pla
 jmp xmd06a ;RETURN
gtxex jmp xmd18 ;USER WANTS TO ABORT
*
* check can,nak appropriate
*
xmd15 inc err ;CANCEL IF 10 ERRORS IN A ROW
 lda #10 ;OTHERWISE JUST nak
 cmp err
 beq xmd18
*
* nak
*
xmd16 lda #'N'
 sta dispr8+18
 lda #nak
 jsr ptxmdm
 rts
*
* eot
*
xmd17 lda #eot
 jsr ptxmdm
 rts
*
* can
*
xmd18 lda #can ;CANCEL THE TRANSFER
 jsr ptxmdm
xmd19 lda #4 ;DISPLAY MESSAGE TO USER
 jsr xmd25
 jsr waittwo
 pla  ;JUMP ALL THE WAY BACK TO
 pla  ;THE bASIC PROGRAM
 rts
xmd28 lda #8 ;ASK USER TO CONFIRM ABORT
 jsr xmd25
xmd28a jsr getkey ;GET KEYBOARD INPUT
 pha
 jsr clrchn
 pla
 pha
 jsr chrout ;DISPLAY USER KEYSTROKE
 pla
 cmp #'Y' ;DID HE CONFIRM ABORT?
 beq xmd19 ;YES - EXIT TRANSFER
 cmp #'N'
 bne xmd28a ;NOT A VALID RESPONSE
 lda #13
 jsr chrout
 lda #0 ;SET TO CONTINUE ON
 rts  ;AND RETURN
*
* complete
*
xmd24 lda #ack ;ACKNOWLEDGE RECEIPT OF eot
 jsr ptxmdm
xmd24a lda #3 ;DISPLAY COMPLETED MESSAGE
xmd25 jsr outmsg
 lda #8 ;CLOSE THE FILE AND GO HOME
 jmp close
*
* send file
*
xmd30 jsr stop ;CHECK IS USING IS PRESSING
 bne xmd30a ;STOP KEY
 jsr xmd19 ;YES - ABORT TRANSFER
xmd30a lda #132
 sta xblsz
 lda ridbs ;CLEAR INPUT BUFFER
 sta ridbe
 lda #0 ;INITIALIZE VARIABLES
 sta tbcount
 sta tbcount+1
 lda #1
 sta bln
 sta blo
 eor #255
 sta blck1
xmd30b jsr stop ;CHECK STOP KEY
 bne xmd30c
 jsr xmd17
 jsr xmd19
xmd30c jsr gim ;GET MODEM CHARACTER
 bne xmd30b ;NO CHARACTER - LOOP
 lda dportb ;CHECK FOR CARRIER
 and carrier
 beq xmd30c1
 jsr xmd28 ;VERIFY ABORT FROM USER
 beq xmd30c
xmd30c1 lda rcvchr
 cmp #can ;IS RECEIVER CANCELLING?
 bne xmd30d ;NO
 jsr xmd19 ;YES - TIME TO QUIT
xmd30d cmp #nak ;WAS TRANSMISSION BAD?
 beq xmd31
 cmp #67
 bne xmd30b ;NO
 lda #10
 jsr outmsg
 lda #133
 sta xblsz
 sta xmode
xmd31 jsr setzero
 lda #3 ;RETRANSMIT LAST BLOCK
 sta chrcnt ;INITIALIZE BLOCK VARIABLES
 ldx #0
 stx cksum
 stx rstat
xmd32 jsr stop ;CHECK STOP KEY
 bne xmd32a
 jmp xmd37x
xmd32a ldx #8 ;GET CHARACTER FROM DISK
 jsr chkin
 jsr getin
 bit tron ;CHECK FOR TRANSLATE ON
 bpl xmd32b ;NO - BYPASS CONVERSION
 jsr cnvrt ;YES - CONVERT TO ASCII
xmd32b sta rcvchr ;STORE THE CHARACTER
 jsr readss ;WATCH DEM DISK ERRORS!
 and #195 ;LOOK FOR END-OF-FILE
 sta rstat ;AND TIME-OUTS
 bne xmd33a
 lda rcvchr ;CALCULATE CHECKSUM WITH
 jsr chkadd ;THIS CHARACTER
 cmp #131 ;GOT A FULL BLOCK YET?
 bne xmd32 ;NO - LOOP
 beq xmd34 ;YES - PROCESS END OF BLOCK
xmd33a = *
 lda rcvchr ;CALCULATE CHECKSUM WITH
 jsr chkadd ;THIS CHARACTER
 cmp #131 ;IS THE BLOCK FULL?
 beq xmd34 ;YES - BYPADD PADDING
 lda #26 ;PAD THE FINAL BLOCK WITH
 sta padchr ;CTRL-Z UNLESS THE LAST
 lda rcvchr ;DATA CHARACTER HAPPENS TO
 cmp #26 ;BE A CTRL-Z
 bne xmd33g ;IF IT IS THEN USE NULL
 lda #0
 sta padchr
xmd33g lda padchr ;PAD OUT THE BLOCK UNTIL
 sta rcvchr ;WE FILL IT UP
xmd38a jsr chkadd
 cmp #131
 bne xmd38a
xmd34 bit xmode ;CHECKSUM OR CRC?
 bpl xmd34a ;CHECKSUM
 lda crc+1 ;FILL IN THE
 sta blch ;16-BIT CRC
 lda crc
 sta blch+1
 jmp xmd34b
xmd34a lda cksum ;FILL IN THE CALCULATED
 sta blch ;CHECKSUM
xmd34b lda #0
 sta tempx
xmd35 jsr stop ;CHECK THE OLD STOP KEY
 beq xmd37x
 ldx tempx ;NOW LET US OUTPUT THE
 lda block,x ;ENTIRE BLOCK TO THE MODEM
 jsr ptxmdm
 lda dportb ;DONT FORGET TO CHECK FOR
 and carrier ;CARRIER LOSS
 beq xmd35b
 jsr xmd28
xmd35b inc tempx ;DID WE FINISH THE BLOCK YET?
 lda xblsz
 cmp tempx
 bne xmd35
 jsr setjif ;SET THE TIMEOUT
xmd36 lda dportb ;BEING CAUTIOUS WE CONTINUE TO
 and carrier ;CHECK FOR CARRIER
 beq xmd36a
 jsr xmd28
xmd36a jsr gim ;LOOK FOR THE RECEIVER RESPONSE
 beq xmd37
 jsr stop ;NO RESPONSE YET - LOOK FOR THE
 beq xmd37x ;STOP KEY
 jsr tstjif ;AND CHECK FOR A TIMEOUT
 bcc xmd36 ;LOOP IF NOT TIMED OUT YET
 bcs xmd34 ;OTHERWISE RETRANSMIT
xmd37 lda rcvchr
 cmp #nak ;DID HE SEND A nak?
 bne xmd37e
 lda #'N' ;UPDATE THE DISPLAY AND GO
 sta dispr8+18 ;BACK TO RETRANSMIT
 jmp xmd34
xmd37e cmp #can ;DID HE SEND CANCEL?
 bne xmd37a
xmd37x jsr xmd19 ;YES - THEN ABORT
xmd37a cmp #ack ;DID HE SEND ack?
 beq xmdack
 cmp #67
 bne xmd36 ;NONE OF THE ABOVE
xmdack lda rstat ;CHECK FOR STATUS NOT ZERO
 beq xmd38 ;NO
 jsr xmd17 ;YES - SEND eot
 jsr setjif ;SET TIMEOUT
xmd37b lda jiffy ;CHECK THE TIMEOUT AND LOOK
 bmi xmd37c ;FOR FINAL RESPONSE FROM
 jsr gim ;THE RECEIVER
 bne xmd37b
xmd37c lda rstat ;CHECK FOR END OF FILE
 and #64
 beq xmd37x ;NO - ABORT
 jmp xmd24a ;YES - DISPLAY COMPLETE
xmd38 inc blo ;INCREMENT THE BLOCK NUMBER
 lda #255
 eor blo
 sta blck1
 jsr xmdblk ;DISPLAY BLOCK STATUS
 jmp xmd31 ;BACK FOR NEXT BLOCK
*
* receive - start crc and switch to chksum if
*           no response
*
xmd60 lda #67 ;SEND 'c' TO INDICATE crc
 jsr ptxmdm ;CAPABILITY
 jsr setjif ;SET TIMER FOR RETRY
xmd60a jsr gim ;LOOK FOR RESPONSE
 beq xmd60b ;YES
 lda jiffy ;NO - IS TIME UP?
 cmp #1
 bne xmd60a ;NO - KEEP LOOKING
 dec ctrys ;YES - DECREMENT TRYS
 bne xmd60 ;NOT FINISHED - TRY AGAIN
 jsr xmd16 ;SWITCH TO CHECKSUM
 rts
xmd60b lda rcvchr ;GET RECEIVED CHARACTER
 cmp #soh ;IS IT START OF XMODEM BLOCK
 bne xmd60a ;NO - IGNORE IT
 lda #133 ;YES
 sta xmode ;SET crc MODE
 sta xblsz ;AND crc TOTAL BLOCK SIZE
 lda #10 ;INFORM THE USER
 jsr outmsg
 rts
*
* get xmodem char
*
gim ldx #5
 jsr chkin
 jsr getin ;TRY FOR CHARACTER
 sta rcvchr ;AND SAVE RESULT
 jsr readss ;NOW CHECK STATUS
 rts
*
* test jiffy
*
tstjif lda jiffy
 cmp #2
 rts
*
* set jiffy
*
setjif lda #0
 sta jiffy
 sta jiffy+1
 rts
*
* put char to modem
*
ptxmdm pha
 ldx #5
 jsr chkout
ptx01 lda enable ;IS RS232 QUIESCENT
 and #3 ;IN BOTH DIRECTIONS
 bne ptx01 ;NO - WAIT UNTIL IT IS
 pla  ;YES - GET CHARACTER
 jsr chrout ;AND SEND IT TO MODEM
 rts
*
* calculate checksum
*
chkadd lda rcvchr
 bit xmode
 bpl chka1
 jsr crcmode
chka1 lda rcvchr
 ldx chrcnt
 sta block,x
 clc
 adc cksum
 sta cksum
 inc chrcnt
 inx
 txa
 rts
*
* crc mode
*
crcmode sta crcdata
 ldx #8
 lda chrcnt
 cmp #3
 bge crcm1
 rts
crcm1 asl crcdata
 ror a
 and #$80
 eor crc+1
 asl crc
 rol a
 bcc crcm2
 tay
 lda crc
 eor ply
 sta crc
 tya
 eor ply+1
crcm2 sta crc+1
 dex
 bne crcm1
 rts
*
* crc init
*
crcinit lda #0
 sta crc
 sta crc+1
 rts
*
* outmsg prompt pointer table
*
prmtbl = *
 da prompt4
 da prmpt13
 da dispr8
 da dispr9
 da dispr10
 da dispr11
 da dispr13
 da buf
 da prmpt10
 da prmpt11
*
* prompts
*
prompt4 dfb 13
 txt 'fILENAME FOR YOUR DISK: '
 dfb 0
prmpt13 dfb 13
 txt 'disk error: '
 dfb 0
dispr8 txt 'tot blk 0000  chk= '
 dfb 13,145,0
dispr9 txt 'transfer complete'
 dfb 13,0
dispr10 txt 'transfer aborted'
 dfb 13,0
dispr11 txt 'xmodem protocol'
 dfb 13,0
dispr13 txt 'iNVALID fILENAME'
 dfb 13,0
prmpt10 txt 'carrior lost: confirm abort Y/N  '
 dfb 0
prmpt11 txt 'USING crc'
 dfb 13,0
*
* output message to device
*
outmsg pha
 ldx #3
 jsr chkout
 pla
 asl a
 tax
 lda prmtbl,x
 sta move
 inx
 lda prmtbl,x
 sta move+1
 ldy #0
outlp1 lda (move),y
 cmp #0
 beq outend
 jsr chrout
 iny
 cpy #0
 bne outlp1
outend rts
*
* check error channel
*
errchn lda #0
 sta buf
 sta ebufx
 ldx #15
 jsr chkin
errl1 jsr getin
 sta rcvchr
 jsr readss
 bne errl2
 lda rcvchr
 ldx ebufx
 sta buf,x
 inc ebufx
 bne errl1
errl2 ldx ebufx
 lda #0
 sta buf,x
 lda #7
 jsr outmsg
 jsr waittwo
 lda buf
 ora buf+1
 and #15
 rts
*
* decimal conversion table
*
dectab dfb 16,39 ; 10,000
 dfb 242,3 ; 1,000
 dfb 100,0 ; 100
 dfb 10,0 ; 10
 dfb 1,0 ; 1
count dfb 0,0
numbr dfb 0,0,0,0,0,32,32,0
tmpcnt dfb 0,0
*
* open disk file a=logical file
*
opendk = *
 tay
 ldx drvdev
 jsr setlfs
 jsr open
 rts
*
* convert to ascii
*
cnvasc ldx #4
 lda #48
cnva4 sta numbr,x
 dex
 bpl cnva4
 inx
cnva1 lda count
 sec
 sbc dectab,x
 sta tmpcnt
 lda count+1
 sbc dectab+1,x
 sta tmpcnt+1
 bcc cnva2
 stx tempx
 txa
 lsr a
 tax
 inc numbr,x
 ldx tempx
 lda tmpcnt
 sta count
 lda tmpcnt+1
 sta count+1
 jmp cnva1
cnva2 inx
 inx
 cpx #10
 bne cnva1
 ldx #4
 rts
*
* display xmodem block
*
xmdblk lda #'A'
 sta dispr8+18
 inc tbcount
 bne xblk2
 inc tbcount+1
xblk2 lda tbcount
 sta count
 lda tbcount+1
 sta count+1
 jsr cnvasc
 ldx #4
xblk1 lda numbr,x
 sta dispr8+7,x
 dex
 bne xblk1
 lda #2
 jsr outmsg
 rts
*
* wait two seconds
*
waittwo jsr setjif
wait2 bit jiffy+1
 bpl wait2
 rts
*
* get a keyboard character
*
getkey ldx #0
 jsr chkin
 jsr getin
 beq getkey
 rts
*
* initialize block variables
*
setzero lda #0
 sta err
 sta chrcnt
 sta cksum
 jsr crcinit ;xmodem crc
 rts
*
* output to screen
*
scnout pha
 ldx #3
 jsr chkout
 pla
 jsr chrout
 rts
